package com.ynet.middleground.contract.service.impl;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.util.List;
import java.util.Map;

import javax.validation.Valid;
import javax.ws.rs.*;
import javax.ws.rs.core.MediaType;

import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.dubbo.config.annotation.Service;
import org.springframework.beans.factory.annotation.Autowired;

import com.google.common.base.Throwables;
import com.ynet.core.common.ServiceResult;
import com.ynet.core.exception.BusinessException;
import com.ynet.core.log.IfpLogger;
import com.ynet.middleground.contract.bean.*;
import com.ynet.middleground.contract.constant.TemplateConsts;
import com.ynet.middleground.contract.dto.TemplateDTO;
import com.ynet.middleground.contract.dto.TemplateDetailDTO;
import com.ynet.middleground.contract.model.TemplateModel;
import com.ynet.middleground.contract.model.TemplateParamModel;
import com.ynet.middleground.contract.service.TemplateService;
import com.ynet.middleground.contract.utils.GeneralService;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;

/**
 * 合约模板处理类
 *
 * @author yangbh
 */
@Produces({MediaType.APPLICATION_JSON + "; " + "charset=UTF-8"})
@Consumes({MediaType.APPLICATION_JSON + "; " + "charset=UTF-8"})
@Api(value = "合约模板管理服务", tags = {"合约模板管理服务"})
@Path("template")
@Service(timeout = 6000, version = "0.0.1")
public class TemplateServiceImpl implements TemplateService, GenericService {

    @Autowired
    private TemplateModel templateModel;

    /**
     * 新增合约模板
     *
     * @param addTemplateReq 新增模板请求类
     * @return 新增模板成功后的模板 id
     */
    @POST
    @ApiOperation(value = "新增模板信息", notes = "新增模板，可一次性把模板信息、参数等信息都新增进来，也可只新增模板信息，再通过参数维护服务来新增参数"
        + "，接口返回新增模板成功后的模板 id<br/>针对制式合同，由金控及各业态风险部相关人员在业务系统渠道端页面进行新建模板操作，新建保存后的模板状态为“未启用”。")
    @ApiImplicitParam(name = "requestObj", dataType = "AddTemplateReq", paramType = "body", required = true)
    @Override
    public ServiceResult<Integer> addTemplate(AddTemplateReq addTemplateReq) {
        ServiceResult<Integer> result = new ServiceResult<>();
        try {
            result.setResult(templateModel.addTemplate(addTemplateReq));
        } catch (BusinessException be) {
            result.setError(be.getCode(), be.getMessage());
        } catch (Exception e) {
            IfpLogger.error(Thread.currentThread().getStackTrace()[1].getMethodName(), "新增模板服务异常, case: {}",
                Throwables.getStackTraceAsString(e));
            result.setError("ECCT0000", "服务异常，请联系系统管理员");
        }
        return result;
    }

    /**
     * 分页查询合约模板列表
     *
     * @param queryTemplateReqPager 分页查询模板信息请求类
     * @return 模板列表
     */
    @POST
    @Path("list")
    @ApiOperation(value = "查询模板列表", notes = "根据查询条件分页查询合约模板列表<br/> 用户可在产融核心渠道前端，根据筛选条件，查询符合条件的模板")
    @ApiImplicitParam(name = "requestObj", dataType = "QueryTemplateReqPager", paramType = "body", required = true)
    @Override
    public ServiceResult<List<TemplateDTO>> listTemplate(@Valid QueryTemplateReqPager queryTemplateReqPager) {
        ServiceResult<List<TemplateDTO>> result = new ServiceResult<>();
        try {
            result.setResult(templateModel.listTemplates(queryTemplateReqPager));
            result.setPagerInfo(queryTemplateReqPager.getPagerInfo());
        } catch (BusinessException be) {
            result.setError(be.getCode(), be.getMessage());
        } catch (Exception e) {
            IfpLogger.error(Thread.currentThread().getStackTrace()[1].getMethodName(), "分页查询模板列表服务异常, case: {}",
                Throwables.getStackTraceAsString(e));
            result.setError("ECCT0000", "服务异常，请联系系统管理员");
        }
        return result;
    }

    /**
     * 根据模板 id 查询模板详情信息
     *
     * @param queryTemplateReq 查询指定模板详情信息请求对象
     * @return 模板详情信息
     */
    @POST
    @Path("detail")
    @ApiOperation(value = "查询模板详情", notes = "根据模板 id 查询模板详情信息<br/>用户可在产融核心渠道前端，查看指定模板详情")
    @ApiImplicitParam(name = "requestObj", dataType = "QueryTemplateReq", paramType = "body", required = true)
    @Override
    public ServiceResult<TemplateDetailDTO> getTemplateById(@Valid QueryTemplateReq queryTemplateReq) {
        ServiceResult<TemplateDetailDTO> result = new ServiceResult<>();
        try {
            result.setResult(templateModel.getTemplateById(queryTemplateReq));
        } catch (BusinessException be) {
            result.setError(be.getCode(), be.getMessage());
        } catch (Exception e) {
            IfpLogger.error(Thread.currentThread().getStackTrace()[1].getMethodName(), "查询模板详情信息服务异常, case: {}",
                Throwables.getStackTraceAsString(e));
            result.setError("ECCT0000", "服务异常，请联系系统管理员");
        }
        return result;
    }

    /**
     * 根据模板 id 删除指定模板
     *
     * @param deleteTemplateReq 删除模板请求类
     * @return 结果标志，以 success 字段值标识 true/false
     */
    @DELETE
    @ApiOperation(value = "删除模板信息", notes = "根据模板参数 id 删除模板信息<br/>由风险部相关人员，在业务系统渠道前端页面，进行删除模板操作（只能对“未启用”的模板进行删除操作）")
    @ApiImplicitParam(name = "requestObj", dataType = "DeleteTemplateReq", paramType = "body", required = true)
    @Override
    public ServiceResult deleteTemplateById(@Valid DeleteTemplateReq deleteTemplateReq) {
        ServiceResult result = new ServiceResult<>();
        try {
            templateModel.deleteTemplateById(deleteTemplateReq);
        } catch (BusinessException be) {
            result.setError(be.getCode(), be.getMessage());
        } catch (Exception e) {
            IfpLogger.error(Thread.currentThread().getStackTrace()[1].getMethodName(), "删除模板信息服务异常, case: {}",
                Throwables.getStackTraceAsString(e));
            result.setError("ECCT0000", "服务异常，请联系系统管理员");
        }
        return result;
    }

    /**
     * 根据模板 id 更新模板基础信息
     *
     * @param updateTemplateReq 修改模板基础信息请求类
     * @return 结果标志，以 success 字段值标识 true/false
     */
    @PUT
    @ApiOperation(value = "更新模板信息",
        notes = "根据模板 id 更新模板基础信息<br/>由风险部相关人员，在业务系统渠道端前端页面，进行修改模板操作（只能对“未启用”或“已停用”的模板进行修改操作）")
    @ApiImplicitParam(name = "requestObj", dataType = "UpdateTemplateReq", paramType = "body", required = true)
    @Override
    public ServiceResult updateTemplateById(@Valid UpdateTemplateReq updateTemplateReq) {
        ServiceResult result = new ServiceResult<>();
        try {
            templateModel.updateTemplateById(updateTemplateReq);
        } catch (BusinessException be) {
            result.setError(be.getCode(), be.getMessage());
        } catch (Exception e) {
            IfpLogger.error(Thread.currentThread().getStackTrace()[1].getMethodName(), "更新模板信息服务异常, case: {}",
                Throwables.getStackTraceAsString(e));
            result.setError("ECCT0000", "服务异常，请联系系统管理员");
        }
        return result;
    }

    /**
     * 更新模板状态
     *
     * @param req 更新模板状态
     * @return 结果标志，以 success 字段值标识 true/false
     */
    @POST
    @Path("updateTemplateStatusById")
    @ApiOperation(value = "更新合约模板状态",
        notes = "更新合约模板状态<br/>规则如下：<br/>①当前状态是0未启用，只能更新状态至1启用中；<br/>" + "②当前状态是1启用中，只能更新状态至0未启用、2已启用；<br/>"
            + "③当前状态是2已启用，只能更新状态至3已停用；<br/>" + "④当前状态是3已停用，只能更新状态至1启用中；<br/>" + "⑤若要将模板状态更新至3已停用，则必须保证当前没有在途合约；")
    @ApiImplicitParam(name = "requestObj", dataType = "UpdateTemplateStatusForChannelReq", paramType = "body",
        required = true)
    @Override
    public ServiceResult updateTemplateStatusById(@Valid UpdateTemplateStatusForChannelReq req) {
        ServiceResult result = new ServiceResult<>();
        try {
            templateModel.updateTemplateStatusById(req);
        } catch (BusinessException be) {
            result.setError(be.getCode(), be.getMessage());
        } catch (Exception e) {
            IfpLogger.error(Thread.currentThread().getStackTrace()[1].getMethodName(), "更新合约模板状态服务异常, case: {}",
                Throwables.getStackTraceAsString(e));
            result.setError("ECCT0000", "服务异常，请联系系统管理员");
        }
        return result;
    }

    /**
     * 判断模板是否可以变更为其他状态 <br />
     * <note> 该接口为审批中心监听器使用 </note>
     *
     * @param req 查询模板是否符合激活或停用的条件
     * @return 结果标志，以 success 字段值标识 true/false
     */
    @POST
    @Path("check-condition")
    @ApiOperation(value = "判断模板是否可以变更为其他状态", notes = "判断模板是否可以变更为其他状态，如想激活模板，判断是否满足激活模板的条件", hidden = true)
    @ApiImplicitParam(name = "requestObj", dataType = "QueryTemplatesConditionReq", paramType = "body", required = true)
    @Override
    public ServiceResult<Object> checkTemplateCondition(@Valid QueryTemplatesConditionReq req) {
        ServiceResult<Object> result = new ServiceResult<>();
        try {
            templateModel.checkTemplateCondition(req);
        } catch (BusinessException be) {
            result.setError(be.getCode(), be.getMessage());
        } catch (Exception e) {
            IfpLogger.error(Thread.currentThread().getStackTrace()[1].getMethodName(), "判断模板是否可以变更为其他状态服务异常, case: {}",
                Throwables.getStackTraceAsString(e));
            result.setError("ECCT0000", "服务异常，请联系系统管理员");
        }
        return result;
    }

    /**
     * 激活模板 <br />
     * <note> 该接口保留勿删，为防止 dubbo 形式调用，不开放 </note>
     *
     * @param updateTemplateStatusReq 更新模板状态请求类
     * @return 结果标志，以 success 字段值标识 true/false
     */
    /*@POST
    @Path("active")
    @ApiOperation(value = "激活模板", notes = "激活模板")
    @ApiImplicitParam(name = "requestObj", dataType = "UpdateTemplateStatusReq", paramType = "body", required = true)
     @Override*/
    private ServiceResult activeTemplate(@Valid UpdateTemplateStatusReq updateTemplateStatusReq) {
        ServiceResult result = new ServiceResult<>();
        try {
            templateModel.activeTemplate(updateTemplateStatusReq);
        } catch (BusinessException be) {
            result.setError(be.getCode(), be.getMessage());
        } catch (Exception e) {
            IfpLogger.error(Thread.currentThread().getStackTrace()[1].getMethodName(), "启用模板信息服务异常, case: {}",
                Throwables.getStackTraceAsString(e));
            result.setError("ECCT0000", "服务异常，请联系系统管理员");
        }
        return result;
    }

    /**
     * 停用模板 <br />
     * <note> 该接口保留勿删，为防止 dubbo 形式调用，不开放 </note>
     *
     * @param updateTemplateStatusReq 更新模板状态请求类
     * @return 结果标志，以 success 字段值标识 true/false
     */
    /*@POST
    @Path("disable")
    @ApiOperation(value = "停用模板", notes = "停用模板")
    @ApiImplicitParam(name = "requestObj", dataType = "UpdateTemplateStatusReq", paramType = "body", required = true)
    @Override*/
    private ServiceResult disableTemplate(@Valid UpdateTemplateStatusReq updateTemplateStatusReq) {
        ServiceResult result = new ServiceResult<>();
        try {
            templateModel.disableTemplate(updateTemplateStatusReq);
        } catch (BusinessException be) {
            result.setError(be.getCode(), be.getMessage());
        } catch (Exception e) {
            IfpLogger.error(Thread.currentThread().getStackTrace()[1].getMethodName(), "停用模板信息服务异常, case: {}",
                Throwables.getStackTraceAsString(e));
            result.setError("ECCT0000", "服务异常，请联系系统管理员");
        }
        return result;
    }

    @Autowired
    TemplateParamModel templateParamModel;
    @Autowired
    GeneralService generalService;

    /**
     * 根据模板生成合约 <br />
     * <note> 该接口仅供测试 poi-tl 引擎生成 word 文件使用，保留勿删，为防止 dubbo 形式调用，不开放 </note>
     *
     * @param templateCommReq 生成合约的请求体信息
     * @return 合约生成信息
     */
    /*@POST
    @Path("generate")
    @Override*/
    private ServiceResult<String> generate(@Valid TemplateCommReq templateCommReq) {
        ServiceResult result = new ServiceResult<>();
        Map<String, Object> params = templateCommReq.getTemplateParams();
        // 合约编号参数key
        String contractNoName = templateParamModel.getContractNoName(templateCommReq.getTemplateId());
        // 合约二维码的参数key
        String contractNoQrCodeName = templateParamModel.getContractNoQrCodeName(templateCommReq.getTemplateId());
        String contractNo = "这是合约编号XXX123";
        if (StringUtils.isNotEmpty(contractNoName)) {
            params.put(contractNoName, contractNo);
        }
        // 二维码字节流
        byte[] qrcode = generalService.getQRCodeImage(contractNo, TemplateConsts.TPL_PARAM_QR_CODE_WEIGHT,
            TemplateConsts.TPL_PARAM_QR_CODE_HEIGHT);
        if (StringUtils.isNotEmpty(contractNoQrCodeName)) {
            params.put(contractNoQrCodeName, qrcode);
        }
        templateCommReq.setTemplateParams(params);
        try {
            // File file = templateModel.generateContract(templateCommReq.getTemplateId(), params);
            File file = templateModel.generateContract(templateCommReq.getTemplateId(),
                templateCommReq.getTemplateParams(), templateCommReq.getTableMergeCells());
            File desktopFile = new File("/Users/suremotoo/Desktop/generate-test.docx");
            FileUtils.copyInputStreamToFile(new ByteArrayInputStream(FileUtils.readFileToByteArray(file)), desktopFile);
        } catch (BusinessException be) {
            result.setError(be.getCode(), be.getMessage());
        } catch (Exception e) {
            IfpLogger.error(Thread.currentThread().getStackTrace()[1].getMethodName(), "服务异常, case: {}",
                Throwables.getStackTraceAsString(e));
            result.setError("ECCT0000", "服务异常，请联系系统管理员");
        }
        return result;
    }

}
